<template>
  <div>
    <!-- 弹框失败提示 -->
    <div class="alert" v-show="isAlert">
      <div class="alert-container"></div>
      <div class="alert-fail">
        <div class="alert-fail-title">{{failText.title}}</div>
        <div class="alert-fail-detail">{{failText.detail}}</div>
        <div class="btn-ground">
          <button @click="open" :disabled="isOpen">重试</button>
          <button @click="close">取消</button>
        </div>
      </div>
    </div>

    <!-- 页面图片展示区 -->
    <div class="sketch">
      <div class="sketch-img"></div>
      <p class="sketch-text">
        正面平视手机、保证光线充足
        <br />请勿遮挡面部
      </p>
    </div>

    <!-- 页面步骤提示 -->
    <div class="prompt">
      <div class="prompt-box">
        <div class="prompt-box-text" v-for="(item , index) in items" :key="index">
          <span class="prompt-box-text-number">{{item.number}}</span>
          <span class="prompt-box-text-content">{{item.text}}</span>
          <span class="prompt-box-text-border" v-if="item.border"></span>
        </div>
      </div>

      <!-- 下一步 -->
      <button
        class="prompt-next"
        @click="open"
        :class="{'prompt-next-disabled' : isNext}"
        :disabled="isNext"
      >{{limitTime | nextClick}}</button>
    </div>

    <!-- 验证码弹框 -->
    <div class="modal-layer" v-show="isCode">
      <div class="modal-layer-mask"></div>
      <div class="modal-layer-popup">
        <div class="modal-layer-success">
          <div class="modal-layer-popup-title">请牢记以下验证码</div>
          <div class="modal-layer-popup-content">
            此验证码将于
            <span>{{validTime}}</span>
            秒后过期
            <br />用普通话朗读数字，视频时长
            <span>3-6&nbsp;</span>秒最佳
          </div>
          <div class="modal-layer-popup-number" v-html="templateObj"></div>
          <div class="modal-wrapper" :class="{'modal-point' : btnPoint}">
            <span class="modal-confirm-btn">{{timeHaveToStay | confirmBtnText}}</span>
            <input
              type="file"
              accept="video/*"
              capture="camcorder"
              :disabled="timeHaveToStay > 0"
              @change="cameraChange($event)"
              class="camera-input video"
            />
          </div>
        </div>
        <span class="modal-layer-close" @click="close"></span>
      </div>
    </div>
    <div class="loading" v-show="isLoading">
      <div class="loading-icon">验证中...</div>
    </div>
  </div>
</template>

<script>
/**
 * 作者 : 李健邦
 * 日期 : 20200606
 * 功能 : H5视频活体人脸识别模块，并未与后台接口进行调试。
 */
export default {
  data() {
    return {
      isNext: false,
      isOpen: false,
      isAlert: false,
      isLoading: false,
      isCode: false,
      btnPoint: false,
      clickNum: 0,
      limitTime: 0, //频繁操作限制时长
      validTime: 0, //验证码有效时长
      timeHaveToStay: 3, //记忆时长
      limitTimer: null,
      validTimer: null,
      stayTimer: null,
      templateObj: "",
      failText: {}, //失败提示信息
      items: [
        {
          number: 1,
          text: "牢记验证码，点击开始录制",
          border: 1
        },
        {
          number: 2,
          text: "开启前置摄像头，用普通话朗读数字",
          border: 1
        },
        {
          number: 3,
          text: "完成录制，等待验证结果",
          border: 0
        }
      ]
    };
  },
  filters: {
    confirmBtnText(val) {
      if (val > 0) {
        return `记住了，开始录制(${val}s)`;
      }
      return "记住了，开始录制";
    },
    nextClick(val) {
      if (val > 0) {
        return `操作太频繁，请您(${val}s)之后再尝试`;
      }
      return "下一步";
    }
  },
  mounted() {
    this.endTime();
  },
  methods: {
    /**
     * desc : 60s倒计时，刷新页面计时器不刷新
     */
    endTime() {
      let endingTime = new Date().getTime() + 60 * 1000;
      let timeInLocalStorage = localStorage.getItem("endingTime");
      if (localStorage.getItem("endingTime")) {
        let diff = timeInLocalStorage - new Date().getTime();
        if (diff <= 0) {
          localStorage.removeItem("endingTime");
        } else {
          let s = Math.floor(diff / 1000);
          this.countDown(s);
          let s2 = s < 10 ? "0" + s : s;
          this.limitTime = s2;
        }
      } else if (this.clickNum >= 5) {
        this.countDown(60);
        this.limitTime = 60;
        localStorage.setItem("endingTime", endingTime);
      }
    },
    /**
     * desc : 动态更新页面时间数据、动态绑定样式、
     *        限制用户点击按钮、重置点击次数
     */
    countDown(second) {
      let s2;
      let self = this;
      let tiem = setInterval(function() {
        second--;
        if (second < 0) {
          localStorage.removeItem("endingTime");
          self.limitTime = 0;
          self.isNext = false;
          clearTimeout(tiem);
          tiem = null;
          return;
        }
        self.isNext = true;
        self.clickNum = 0;
        s2 = second < 10 ? "0" + second : second;
        self.limitTime = s2;
      }, 1000);
    },
    /**
     * desc : 手动清除定时器
     */
    clearTimer() {
      this.stayTimer && clearTimeout(this.stayTimer);
      this.validTimer && clearTimeout(this.validTimer);
      this.stayTimer = null;
      this.validTimer = null;
    },
    /**
     * desc : 记忆时间
     */
    stayTimerF() {
      this.stayTimer = setTimeout(() => {
        if (--this.timeHaveToStay === 0) {
          clearTimeout(this.stayTimer);
          this.stayTimer = null;
          this.btnPoint = true;
          return;
        }
        this.stayTimerF();
      }, 1000);
    },
    /**
     * desc : 验证码有效时间,后期验证码需来自服务端
     */
    setTime(seconds) {
      if (seconds > 1) {
        seconds--;
        this.validTime = seconds;
        this.validTimer = setTimeout(() => {
          this.setTime(seconds);
        }, 1000);
      } else {
        this.templateObj =
          "<span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span>";
        this.setTime(60);
        this.timeHaveToStay = 3;
        this.btnPoint = false;
        this.stayTimerF();
      }
    },
    /**
     * desc : 点击次数累加,累加到5次之后，限制用户60s内，
     *        不能进行人脸识别验证
     */
    open() {
      this.clickNum++;
      if (this.clickNum < 5) {
        this.setTime(60);
        this.timeHaveToStay = 3;
        this.btnPoint = false;
        this.stayTimerF();
        this.isAlert = false;
        this.isCode = true;
        this.templateObj =
          "<span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span><span>" +
          Math.floor(Math.random() * 10) +
          "</span>";
      } else {
        this.endTime();
        this.isOpen = true;
        this.isCode = false;
        this.isAlert = true;
        this.failText = {
          title: "失败提示",
          detail: `你操作太频繁，请60s之后再尝试`
        };
      }
    },
    close() {
      this.clearTimer();
      this.isAlert = false;
      this.isCode = false;
    },
    /**
     * desc : 活体校验，监听input change事件，视频大小限制在10m以内
     *        并未与后台服务对接
     */
    cameraChange(event) {
      this.isCode = false;
      const files = event.target.files;
      this.isLoading = true;
      var self = this;

      if (files && files.length > 0) {
        var file = files[0];
        if (file.size > 10 * 1024 * 1024) {
          this.isLoading = false;
          this.isAlert = true;
          this.isCode = false;
          this.failText = {
            title: "失败提示",
            detail: "录制视频时间太长，建议在3-6秒"
          };
          this.clearTimer();
          return;
        }
        async function send() {
          var Data = await getVideo();
          self.$axios
            .post("/api/check_facing1", Data)
            .then(res => {
              console.log(res.data);
              self.isLoading = false;
            })
            .catch(err => {
              self.isLoading = false;
              self.isAlert = true;
              self.failText = {
                title: "视频上传失败",
                detail: "请重新上传"
              };
            });
        }
        function getVideo() {
          return new Promise(function(resolve, reject) {
            var reader = new FileReader();
            reader.readAsDataURL(file);
            var formdata = {};
            reader.addEventListener("loadend", function() {
              formdata = {
                type: "faceliveness_verify",
                video_base64: reader.result.split(",")[1]
              };
              resolve(formdata);
            });
          });
        }
        send();
        this.clearTimer();
      }
    }
  },
  destroyed() {
    this.clearTimer();
  }
};
</script>

<style>
.alert {
  width: 100%;
  height: auto;
}
.alert,
.alert-container {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
.alert-container {
  opacity: 0.45;
  background: #000;
  z-index: 1;
}
.alert-fail {
  width: 24.083rem;
  height: 14.666rem;
  background-color: #fff;
  padding: 0 0.833rem 0.833rem;
  position: fixed;
  left: 50%;
  top: 10.666rem;
  margin-left: -12.85rem;
  z-index: 2;
}
.alert-fail-title {
  font-size: 16px;
  color: #333;
  height: 1.333rem;
  line-height: 1.333rem;
  text-align: center;
  margin: 3.083rem 0 1.25rem;
}
.alert-fail-detail {
  font-size: 1.166rem;
  color: #666;
  text-align: center;
  margin-bottom: 1.71rem;
  letter-spacing: 0;
}
.btn-ground {
  display: flex;
  flex-flow: row nowrap;
  justify-content: space-between;
}
.btn-ground button {
  text-align: center;
  background: #ed171f;
  display: block;
  width: 5.666rem;
  margin: 0 auto;
  font-size: 14px;
  color: #fff;
  font-weight: 700;
  height: 36px;
  border-radius: 12px;
  line-height: 36px;
  border: 1px solid red;
}
.sketch {
  background: hsla(0, 0%, 88%, 0.35);
  padding: 0.8333rem 1.666rem 1.2rem;
}
.sketch-img {
  width: 14.916rem;
  height: 21.583rem;
  margin: 0 auto;
  background: url(./images/sketch.png) 0 0 no-repeat;
  -moz-background-size: 100% auto;
  background-size: 100% auto;
}
.sketch-text {
  font-size: 14px;
  color: #999;
  letter-spacing: 0;
  line-height: 24px;
  text-align: center;
}
.prompt {
  -webkit-box-shadow: 0 -4px 10px 0 #e8e8e8;
  -moz-box-shadow: 0 -4px 10px 0 #e8e8e8;
  box-shadow: 0 -4px 10px 0 #e8e8e8;
  padding-bottom: 0.833rem;
}
.prompt-box {
  padding: 4.166rem 0;
}
.prompt-box-text {
  margin: 0 auto 2.666rem;
  height: 1.334rem;
  line-height: 1.334rem;
  width: 23.5rem;
}
.prompt-box-text:last-child {
  margin-bottom: 0;
}
.prompt-box-text-number {
  -webkit-border-radius: 200px;
  -moz-border-radius: 200px;
  border-radius: 200px;
  border: 1px solid #0073eb;
  text-align: center;
  color: #0073eb;
  display: inline-block;
  width: 1.334rem;
  height: 1.333rem;
  line-height: 1.333rem;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  font-size: 12px;
  margin-right: 0.833rem;
  letter-spacing: 0;
  vertical-align: top;
}
.prompt-box-text-content {
  color: #333;
  letter-spacing: 0;
  white-space: nowrap;
  display: inline-block;
  font-size: 1.333rem;
}
.prompt-box-text-border {
  height: 1.9rem;
  margin: 0.417rem 0 0.417rem 0.59rem;
  width: 0;
  border-left: 1px dotted #0073eb;
  display: block;
}
.prompt-next {
  border: 5px solid red;
  margin: 0 auto;
  height: 4.083rem;
  line-height: 4.083rem;
  text-align: center;
  background: #0073eb;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  color: #fff;
  display: block;
  width: 28.75rem;
  font-size: 16px;
  outline: none;
  border: none;
}
.prompt-next-disabled {
  background: #9da0a3;
}

.modal-layer {
  width: 100%;
  height: auto;
}
.modal-layer,
.modal-layer-mask {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
.modal-layer-mask {
  opacity: 0.45;
  background: #000;
  z-index: 1;
}
.modal-layer-popup {
  width: 24.083rem;
  height: 22.666rem;
  background-color: #fff;
  padding: 0 0.833rem 0.833rem;
  position: fixed;
  left: 50%;
  top: 10.666rem;
  margin-left: -12.85rem;
  z-index: 2;
}
.modal-layer-popup-title {
  font-size: 16px;
  color: #333;
  height: 1.333rem;
  line-height: 1.333rem;
  text-align: center;
  margin: 3.083rem 0 1.25rem;
}
.modal-layer-popup-content {
  font-size: 1.166rem;
  color: #666;
  text-align: center;
  margin-bottom: 1.71rem;
  letter-spacing: 0;
}
.modal-layer-popup-content span {
  color: red;
}
.modal-layer-popup-number {
  font-size: 0;
  text-align: center;
}
.modal-layer-popup-number span {
  font-size: 40px;
  color: #333;
  display: inline-block;
  width: 3.65rem;
  height: 5rem;
  line-height: 5rem;
  margin-right: 0.43rem;
  border: 1px solid #e1e1e1;
  -webkit-border-radius: 10px;
  -moz-border-radius: 10px;
  border-radius: 10px;
  text-align: center;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.modal-layer-popup-number span:last-child {
  margin-right: 0;
}
.modal-layer-close {
  outline: none;
  position: absolute;
  width: 3.666rem;
  height: 3.666rem;
  left: 50%;
  bottom: -9.875rem;
  margin-left: -1.833rem;
  background: url(./images/icon_close.png) 0 0 no-repeat;
  -moz-background-size: 100% auto;
  background-size: 100% auto;
}
.modal-layer-fail-icon {
  width: 3.192rem;
  height: 2.74rem;
  margin: 2.096rem auto 2.925rem;
  background: url(./images/icon_fail.png) 0 0 no-repeat;
  -moz-background-size: 100% auto;
  background-size: 100% auto;
}
.modal-layer-fail-title {
  text-align: center;
  font-size: 1.5rem;
  color: #333;
  margin-bottom: 0.6rem;
}
.modal-layer-fail-detail {
  font-size: 1.166rem;
  color: #666;
  text-align: center;
}
.modal-layer-fail-restart {
  background: #0073eb;
  font-size: 1.333rem;
  color: #fff;
}
.modal-layer-fail-restart,
.modal-layer .modal-wrapper {
  height: 4.083rem;
  text-align: center;
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  line-height: 4.083rem;
  position: absolute;
  width: 24rem;
  bottom: 0.84rem;
}
.modal-layer .modal-wrapper {
  background: #9da0a3;
}
.modal-layer .modal-wrapper.modal-point {
  background: #0073eb;
}
.modal-layer .modal-confirm-btn {
  font-size: 16px;
  color: #fff;
  width: 100%;
  height: 100%;
}
.modal-layer .camera-input {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
}
.loading {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 10;
}
.loading-icon {
  width: 4.667rem;
  height: 5rem;
  background: url(./images/loading.png) center 0 no-repeat;
  -moz-background-size: 50% 50%;
  background-size: 50% 50%;
  position: absolute;
  left: 50%;
  margin-left: -2.334rem;
  top: 50%;
  margin-top: -2.5rem;
  text-align: center;
  font-size: 1.166rem;
  color: #fff;
  line-height: 8rem;
}
.result {
  background: #e1e1e1;
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  padding: 1.25rem;
}
.result-box {
  background: #fff;
  -webkit-box-shadow: 0 -4px 10px 0 #e8e8e8;
  -moz-box-shadow: 0 -4px 10px 0 #e8e8e8;
  box-shadow: 0 -4px 10px 0 #e8e8e8;
  padding: 3.333rem 5.75rem 4rem;
  margin-bottom: 1.25rem;
}
.result-box-pic {
  display: block;
  width: 17.25rem;
  height: 17.25rem;
  margin: 0 auto 2.333rem;
  position: relative;
  text-align: center;
}
.result-box-pic-icon {
  position: absolute;
  width: 1.677rem;
  height: 1.677rem;
}
.result-box-pic .icon-top {
  left: 0;
  top: 0;
  background: url(./images/icon_left_top.png) 0 0 no-repeat;
  -moz-background-size: 50% 50%;
  background-size: 50% 50%;
}
.result-box-pic .icon-right {
  right: 0;
  top: 0;
  background: url(./images/icon_right_top.png) 0.833rem 0 no-repeat;
  -moz-background-size: 50% 50%;
  background-size: 50% 50%;
}
.result-box-pic .icon-bottom {
  right: 0;
  bottom: 0;
  background: url(./images/icon_right_bottom.png) 0.833rem 0.833rem no-repeat;
  -moz-background-size: 50% 50%;
  background-size: 50% 50%;
}
.result-box-pic .icon-left {
  left: 0;
  bottom: 0;
  background: url(./images/icon_left_bottom.png) 0 0.833rem no-repeat;
  -moz-background-size: 50% 50%;
  background-size: 50% 50%;
}
.result-box-pic .result-box-return-img {
  width: 10.25rem;
  display: block;
  position: absolute;
  left: 50%;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}
.result-box-text {
  font-size: 1.5rem;
  color: #00002d;
  display: block;
  text-align: center;
  height: 4rem;
  margin-bottom: 3.542rem;
}
.result-box-color {
  margin-bottom: 2rem;
}
.result-box-color.resulr-color-red {
  color: #f30;
}
.result-box-color.resulr-color-green {
  color: #30ac69;
}
.result-box-failcolor {
  color: #999;
  font-size: 1.166rem;
  display: block;
  text-align: center;
}
.result-box-value {
  width: 15rem;
  margin: 0 auto;
}
.result-box-value-text {
  color: #999;
  font-size: 1.333rem;
  margin-bottom: 1.25rem;
  display: block;
}
.result-box-value-text:last-child {
  margin-bottom: 0;
}
.result-option {
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
}
.result-option-btn {
  -webkit-border-radius: 4px;
  -moz-border-radius: 4px;
  border-radius: 4px;
  text-align: center;
  -webkit-box-flex: 1;
  -webkit-flex: 1;
  -moz-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
  height: 4.083rem;
  line-height: 4.083rem;
  font-size: 1.333rem;
}
.result-option-btn.result-option-btn-ok {
  background: #0073eb;
  color: #fff;
  border: 1px solid #0073eb;
  margin-right: 1.25rem;
}
.result-option-btn.result-option-btn-again {
  color: #0073eb;
  background: #f5f5f5;
  border: 1px solid #0073eb;
}
</style>
